{{ define "main" }}
<section class="row td-search-result">
<div class="col-12 col-md-8 offset-md-2">
<div class="search-info">
  <div style="display: flex; align-items: center; overflow: hidden;">
    <h2 class="mb-3 mr-3">
      {{ .Title }} for
      <span class="search-query"></span>
    </h2>
    <span class="search-loader"></span>
  </div>
  <div class="search-numbers mt-1"></div>
</div>
<hr>
<div class="search-results"></div>
{{ with .Site.Params }}
<script>
  (() => {
    const cx = '{{ .gcs_engine_id }}';
    const api = '{{ getenv "CUSTOM_SEARCH_KEY" }}';
    // Get query string
    const thisURL = new URL(document.location);
    const { searchParams } = thisURL;
    const queryStr = searchParams.get('q');
    // Set query string to title
    $('.search-query')[0].innerHTML = ` <em>${queryStr}</em>`;

    const showError = (data = {}) => {
      const { error = {} } = data;
      const { code } = error;
      const errMessage = `
        <div class="search-no-results">
          Uh oh. Encountered a${code ? ` ${code}` : 'n'} error while searching for results. Please refresh or try your search again.
        </div>
      `;
      // Remove spinner since error was found
      $('.search-loader')[0].innerHTML = ``;
      $('.search-results')[0].innerHTML = errMessage;
      // Scroll position to top of page once new page has loaded
      window.scrollTo(0, 0);
    };

    const fetchResults = ({ newIndex = 1 }) => {
      // Set spinner next to title while fetch is in progress
      $('.search-loader')[0].innerHTML = `<i class="fas fa-circle-notch fa-spin" style="color: #403F4C"></i>`;
      const searchUrl = 'https://' + `www.googleapis.com/customsearch/v1/siterestrict?key=${api}&cx=${cx}&start=${newIndex}&count=10&q=${encodeURIComponent(queryStr)}`;
      fetch(searchUrl)
        .then(resp => resp.json())
        .then(data => {
          if (data && data.queries) {
            const { queries, searchInformation } = data;
            const { request, previousPage, nextPage } = queries;
            const { totalResults, formattedSearchTime } = searchInformation;
            const { searchTerms } = request[0];
            const hasResults = data && data.items && data.items.length;
            const hasPrev = previousPage && previousPage.length;
            const hasNext = nextPage && nextPage.length;
            // As JSON API has a limit of 100 results, set index accordingly
            const endPageIndex = hasNext ?
              +totalResults >= 100
                ? 91
                : +totalResults - (+totalResults % 10) + 1
              : 1;
            // Account for case where no results are returned
            const noResults = `
              <div class="search-no-results">
                No results found. Please modify your search and try again.
              </div>
            `;
            // Create template for each search result
            const searchResult = item => {
              const { htmlTitle, link, htmlFormattedUrl, snippet } = item;
              // Add bold tags around every search term provided
              const boldSearchTerms = terms => {
                let formattedSnippet = snippet;
                terms.forEach(term => {
                  const boldRegex = new RegExp('(^|)(' + term + ')(|$)','ig')
                  formattedSnippet = formattedSnippet.replace(boldRegex, '$1<b>$2</b>$3');
                })
                return formattedSnippet;
              };
              return `
                <div class="search-result mb-4">
                  <div class="result-title"><a href="${link}">${htmlTitle}</a></div>
                  <div class="result-link">${htmlFormattedUrl}</div>
                  <div class="result-snippet">${boldSearchTerms(searchTerms.split(' '))}</div>
                </div>
              `;
            }
            const pagination = `
              <div class="search-pagination mb-1">
                <button class="search-start" ${hasPrev ? '' : 'disabled'}><i class="fas fa-angle-double-left"></i></button>
                <button class="search-prev" ${hasPrev ? '' : 'disabled'}><i class="fas fa-angle-left"></i></button>
                <button class="search-next" ${hasNext ? '' : 'disabled'}><i class="fas fa-angle-right"></i></button>
                <button class="search-end" ${hasNext ? '' : 'disabled'}><i class="fas fa-angle-double-right"></i></button>
              </div>
            `;
            const searchResults = hasResults ? data.items.map(searchResult) : noResults;
            // Remove spinner when fetch has completed
            $('.search-loader')[0].innerHTML = ``;
            $('.search-numbers')[0].innerHTML = `${hasResults ? 'About ' : ''}${totalResults} results (${formattedSearchTime} seconds)`;
            $('.search-results')[0].innerHTML = [hasResults ? pagination : ''].concat(searchResults, hasResults ? pagination : '').join('');
            $('.search-start').click(() => fetchResults({ newIndex: 1 }));
            $('.search-prev').click(ev => fetchResults({ newIndex: hasPrev ? previousPage[0].startIndex : 1 }));
            $('.search-next').click(ev => fetchResults({ newIndex: hasNext ? nextPage[0].startIndex : 1 }));
            $('.search-end').click(() => fetchResults({ newIndex: endPageIndex }));
            // Scroll position to top of page once new page has loaded
            window.scrollTo(0, 0);
          } else {
            showError(data);
          }
        })
        .catch(showError);
    };

    fetchResults({});
  })()
</script>
{{ end }}
</div>
</section>

{{ end }}